package com.github.llyb120.driver.qiuya;

import com.github.llyb120.json.Json;
import com.github.llyb120.json.Obj;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;

import javax.security.auth.callback.Callback;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;


public class WebSocket {

    private String url = null;
//    private volatile boolean reconnecting = false;
//    private WebSocketClient ws;
    BlockingQueue<Message> dealQueue = new LinkedBlockingQueue<>();
    Map<String, Message> acks = new ConcurrentHashMap<>();
    ExecutorService executor = Executors.newCachedThreadPool();
    BlockingQueue<MyWebSocketClient> openPool = new LinkedBlockingQueue<>();

    public WebSocket(String url) {
        this.url = url;
        this.init();
    }

    private void init() {
        URI uri = null;
        try {
            uri = new URI(url);
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
        for (int i = 0; i < 16; i++) {
            new MyWebSocketClient(this, uri, i);
        }
    }

    public Future<Obj> send(String event, Object data){
        Message msg = new Message(event, null, Json.stringify(data));
        CountDownLatch cl = new CountDownLatch(1);
        msg.cd = cl;
        //锁定map
        acks.put(msg.ack, msg);

        //做出异步结果
        Future<Obj> future = executor.submit(new Callable<Obj>() {
            @Override
            public Obj call() throws Exception {
                cl.await(30, TimeUnit.SECONDS);
                acks.remove(msg.ack);
                return msg.result;
            }
        });

        executor.execute(() -> {
            //拿出一个可用的连接
            MyWebSocketClient ws = null;
            try {
                long before = System.currentTimeMillis();
                ws = openPool.take();
                if(System.currentTimeMillis() - before > 30000){
                    return;
                }
                ws.send(String.format("%s %s %s", msg.event, msg.ack, msg.content));
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                if(ws != null && ws.isOpen()){
                    try {
                        openPool.put(ws);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        return future;
    }


}
